package cn.iocoder.yudao.module.system.service.subjectcombination;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.controller.admin.subjectcombination.vo.*;
import cn.iocoder.yudao.module.system.convert.subjectcombination.SubjectCombinationConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.subjectcombination.SubjectCombinationDO;
import cn.iocoder.yudao.module.system.dal.mysql.subjectcombination.SubjectCombinationMapper;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;

/**
 * 选科组合 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
public class SubjectCombinationServiceImpl implements SubjectCombinationService {

    @Resource
    private SubjectCombinationMapper subjectCombinationMapper;

    // 科目映射表
    private static final Map<String, String> SUBJECT_MAP = new HashMap<>();
    static {
        SUBJECT_MAP.put("物", "物理");
        SUBJECT_MAP.put("化", "化学");
        SUBJECT_MAP.put("生", "生物");
        SUBJECT_MAP.put("政", "政治");
        SUBJECT_MAP.put("史", "历史");
        SUBJECT_MAP.put("地", "地理");
        SUBJECT_MAP.put("技", "技术");
    }

    // 反向映射表
    private static final Map<String, String> REVERSE_SUBJECT_MAP = new HashMap<>();
    static {
        REVERSE_SUBJECT_MAP.put("物理", "物");
        REVERSE_SUBJECT_MAP.put("化学", "化");
        REVERSE_SUBJECT_MAP.put("生物", "生");
        REVERSE_SUBJECT_MAP.put("政治", "政");
        REVERSE_SUBJECT_MAP.put("历史", "史");
        REVERSE_SUBJECT_MAP.put("地理", "地");
        REVERSE_SUBJECT_MAP.put("技术", "技");
    }

    @Override
    public Long createSubjectCombination(@Valid SubjectCombinationCreateReqVO createReqVO) {
        // 插入
        SubjectCombinationDO subjectCombination = SubjectCombinationConvert.INSTANCE.convert(createReqVO);
        subjectCombinationMapper.insert(subjectCombination);
        // 返回
        return subjectCombination.getId();
    }

    @Override
    public void updateSubjectCombination(@Valid SubjectCombinationUpdateReqVO updateReqVO) {
        // 校验存在
        validateSubjectCombinationExists(updateReqVO.getId());
        // 更新
        SubjectCombinationDO updateObj = SubjectCombinationConvert.INSTANCE.convert(updateReqVO);
        subjectCombinationMapper.updateById(updateObj);
    }

    @Override
    public void deleteSubjectCombination(Long id) {
        // 校验存在
        validateSubjectCombinationExists(id);
        // 删除
        subjectCombinationMapper.deleteById(id);
    }

    private void validateSubjectCombinationExists(Long id) {
        if (subjectCombinationMapper.selectById(id) == null) {
            throw exception(SUBJECT_COMBINATION_NOT_EXISTS);
        }
    }

    @Override
    public SubjectCombinationDO getSubjectCombination(Long id) {
        return subjectCombinationMapper.selectById(id);
    }

    @Override
    public List<SubjectCombinationDO> getSubjectCombinationList(Collection<Long> ids) {
        return subjectCombinationMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<SubjectCombinationDO> getSubjectCombinationPage(SubjectCombinationPageReqVO pageReqVO) {
        return subjectCombinationMapper.selectPage(pageReqVO);
    }

    @Override
    public List<SubjectCombinationDO> getSubjectCombinationList(SubjectCombinationPageReqVO exportReqVO) {
        return subjectCombinationMapper.selectList(exportReqVO);
    }

    @Override
    public SubjectCombinationDO getByCombinationCode(String combinationCode) {
        return subjectCombinationMapper.selectByCombinationCode(combinationCode);
    }

    @Override
    public SubjectCombinationDO autoCreateSubjectCombination(String combinationCode) {
        // 先检查是否已存在
        SubjectCombinationDO existing = getByCombinationCode(combinationCode);
        if (existing != null) {
            return existing;
        }

        // 验证组合有效性
        if (!validateCombination(combinationCode)) {
            throw exception(INVALID_SUBJECT_COMBINATION, combinationCode);
        }

        // 解析科目列表
        List<String> subjects = parseSubjectsFromCode(combinationCode);
        
        // 创建新的选科组合
        SubjectCombinationDO combination = new SubjectCombinationDO();
        combination.setCombinationCode(combinationCode);
        combination.setCombinationName(generateCombinationName(subjects));
        combination.setSubjects(JsonUtils.toJsonString(subjects));
        combination.setCategory(determineCombinationCategory(subjects));
        combination.setDescription("自动创建的选科组合");
        combination.setSortOrder(999); // 自动创建的排在后面
        combination.setStatus(1); // 默认启用
        
        subjectCombinationMapper.insert(combination);
        return combination;
    }

    @Override
    public List<String> parseSubjectsFromCode(String combinationCode) {
        if (combinationCode == null || combinationCode.isEmpty()) {
            return new ArrayList<>();
        }

        List<String> subjects = new ArrayList<>();
        
        // 逐字符解析
        for (char c : combinationCode.toCharArray()) {
            String subject = SUBJECT_MAP.get(String.valueOf(c));
            if (subject != null) {
                subjects.add(subject);
            }
        }
        
        return subjects;
    }

    @Override
    public String generateCombinationCode(List<String> subjects) {
        if (subjects == null || subjects.isEmpty()) {
            return "";
        }
        
        StringBuilder code = new StringBuilder();
        for (String subject : subjects) {
            String shortName = REVERSE_SUBJECT_MAP.get(subject);
            if (shortName != null) {
                code.append(shortName);
            }
        }
        
        return code.toString();
    }

    @Override
    public String generateCombinationName(List<String> subjects) {
        if (subjects == null || subjects.isEmpty()) {
            return "";
        }
        
        return String.join("+", subjects);
    }

    @Override
    public String determineCombinationCategory(List<String> subjects) {
        if (subjects == null || subjects.isEmpty()) {
            return "未知";
        }
        
        // 判断是否包含物理或历史
        boolean hasPhysics = subjects.contains("物理");
        boolean hasHistory = subjects.contains("历史");
        
        if (hasPhysics && hasHistory) {
            return "混合";
        } else if (hasPhysics) {
            return "物理方向";
        } else if (hasHistory) {
            return "历史方向";
        } else {
            // 传统理科文科判断
            boolean hasTraditionalScience = subjects.contains("物理") || subjects.contains("化学") || subjects.contains("生物");
            boolean hasTraditionalLiberal = subjects.contains("政治") || subjects.contains("历史") || subjects.contains("地理");
            
            if (hasTraditionalScience && !hasTraditionalLiberal) {
                return "理科";
            } else if (hasTraditionalLiberal && !hasTraditionalScience) {
                return "文科";
            } else {
                return "新高考";
            }
        }
    }

    @Override
    public boolean validateCombination(String combinationCode) {
        if (combinationCode == null || combinationCode.isEmpty()) {
            return false;
        }
        
        // 检查长度（一般选3门）
        if (combinationCode.length() != 3) {
            return false;
        }
        
        // 检查每个字符是否为有效科目
        for (char c : combinationCode.toCharArray()) {
            if (!SUBJECT_MAP.containsKey(String.valueOf(c))) {
                return false;
            }
        }
        
        // 检查是否有重复科目
        Set<Character> uniqueChars = new HashSet<>();
        for (char c : combinationCode.toCharArray()) {
            if (!uniqueChars.add(c)) {
                return false; // 有重复
            }
        }
        
        return true;
    }

    @Override
    public List<SubjectCombinationDO> getAllEnabledCombinations() {
        return subjectCombinationMapper.selectAllEnabled();
    }

    @Override
    public List<SubjectCombinationDO> getEnabledCombinationsByCategory(String category) {
        return subjectCombinationMapper.selectEnabledByCategory(category);
    }

    @Override
    public List<SubjectCombinationDO> getCombinationsBySubject(String subjectName) {
        return subjectCombinationMapper.selectBySubject(subjectName);
    }

    @Override
    public void createDefaultCombinations() {
        // 定义默认的选科组合
        String[][] defaultCombinations = {
            {"物化生", "物理+化学+生物", "新高考", "传统理科组合"},
            {"物化地", "物理+化学+地理", "新高考", "物理化学地理组合"},
            {"物生地", "物理+生物+地理", "新高考", "物理生物地理组合"},
            {"物化政", "物理+化学+政治", "新高考", "物理化学政治组合"},
            {"物生政", "物理+生物+政治", "新高考", "物理生物政治组合"},
            {"物地政", "物理+地理+政治", "新高考", "物理地理政治组合"},
            {"史化生", "历史+化学+生物", "新高考", "历史化学生物组合"},
            {"史化地", "历史+化学+地理", "新高考", "历史化学地理组合"},
            {"史生地", "历史+生物+地理", "新高考", "历史生物地理组合"},
            {"史化政", "历史+化学+政治", "新高考", "历史化学政治组合"},
            {"史生政", "历史+生物+政治", "新高考", "历史生物政治组合"},
            {"史地政", "历史+地理+政治", "新高考", "传统文科组合"}
        };
        
        int sortOrder = 1;
        for (String[] combo : defaultCombinations) {
            // 检查是否已存在
            if (getByCombinationCode(combo[0]) == null) {
                SubjectCombinationDO combination = new SubjectCombinationDO();
                combination.setCombinationCode(combo[0]);
                combination.setCombinationName(combo[1]);
                combination.setSubjects(JsonUtils.toJsonString(parseSubjectsFromCode(combo[0])));
                combination.setCategory(combo[2]);
                combination.setDescription(combo[3]);
                combination.setSortOrder(sortOrder++);
                combination.setStatus(1);
                
                subjectCombinationMapper.insert(combination);
            }
        }
    }

    @Override
    public void updateCombinationStatus(Long id, Integer status) {
        // 校验存在
        validateSubjectCombinationExists(id);
        
        // 更新状态
        SubjectCombinationDO updateObj = new SubjectCombinationDO();
        updateObj.setId(id);
        updateObj.setStatus(status);
        subjectCombinationMapper.updateById(updateObj);
    }

}